package com.haiziwang.yst.util;

import com.google.common.collect.Iterables;
import com.google.common.collect.Lists;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import javax.xml.bind.JAXBContext;
import javax.xml.bind.Marshaller;
import javax.xml.bind.Unmarshaller;
import java.io.StringReader;
import java.io.StringWriter;
import java.util.ArrayList;
import java.util.List;

public class XmlUtils {

    private static final Logger logger = LoggerFactory.getLogger(XmlUtils.class);

    private static List<Class<?>> getAllSuperTypes(Class<?> type) {
        List<Class<?>> result = new ArrayList<Class<?>>();
        for (; type != null; type = type.getSuperclass()) {
            result.add(type);
        }

        return result;
    }

    /**
     * xml -> object
     *
     * @param childClass
     * @return
     */
    public static <T> T unmarshal(String xml, Class<T> childClass) {
        try {
            Class<?>[] reverseAndToArray = Iterables.toArray(Lists.reverse(getAllSuperTypes(childClass)), Class.class);
            JAXBContext jaxbCtx = JAXBContext.newInstance(reverseAndToArray);
            Unmarshaller unmarshaller = jaxbCtx.createUnmarshaller();

            return (T) unmarshaller.unmarshal(new StringReader(xml));
        } catch (Exception e) {
            e.printStackTrace();
            logger.error("xml convert to object failed!", e);
        }
        return null;
    }

    /**
     * object -> xml
     *
     * @param object
     */
    public static String marshal(Object object) {
        String xmlStr = StringUtils.EMPTY;
        if (object == null) {
            return xmlStr;
        }
        try {
            JAXBContext jaxbCtx = JAXBContext.newInstance(object.getClass());

            Marshaller marshaller = jaxbCtx.createMarshaller();
//            marshaller.setProperty(Marshaller.JAXB_FRAGMENT, Boolean.TRUE);
            marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, Boolean.TRUE);
            marshaller.setProperty(Marshaller.JAXB_ENCODING, "UTF-8");

            StringWriter sw = new StringWriter();
            marshaller.marshal(object, sw);

            xmlStr = sw.toString();
            xmlStr = StringUtils.replace(xmlStr, "\n", "\r\n");
        } catch (Exception e) {
            xmlStr = StringUtils.EMPTY;
            logger.error("object convert to xml failed!", e);
            e.printStackTrace();
        }
        return xmlStr;
    }

}
